---
title: OBRetentionService architecture
summary: How the OBRetentionService proxy is generated, constructed, configured, invoked, and held for the lifetime of the run.
status: draft
owner: ProcessOB3PRetention team
last_reviewed: 2026-10-22
---

# OBRetentionService architecture

The `ProcessOB3PRetention` console application reaches the `ThirdPartyArchivalService`† through one hand-written wrapper, `OnBaseService`, which constructs a generated `HylandOutBoundContractClient` and calls its single operation. The client is created once while Autofac resolves the wrapper and is reused for every batch in the run.

## Proxy mechanism

| Aspect | Finding |
| --- | --- |
| Mechanism | `service-reference` (svcutil), evidenced by `ProcessOB3PRetention/Connected Services/OBRetentionService/Reference.svcmap` and `Reference.cs` |
| Proxy type | `HylandOutBoundContractClient` in namespace `ProcessOB3PRetention.OBRetentionService` |
| Base type | `System.ServiceModel.ClientBase<HylandOutBoundContract>` |
| Contract type | `HylandOutBoundContract` |
| Constructed in | `OnBaseService` constructor (`ProcessOB3PRetention/Services/OnBaseService.cs:17`) |
| Binding configured in | `<system.serviceModel><bindings><basicHttpBinding>` in `ProcessOB3PRetention/App.config` |
| Address supplied by | Constructor argument read from the setting `ProcessOB3PRetention.WSPEndPointUrl` (`ProcessOB3PRetention/Services/OnBaseService.cs:19`) |

Generation options recorded in `Reference.svcmap` are task-based asynchronous methods enabled, synchronous methods generated, public generated types, and no message contracts. They are generator configuration, not design.

## Architecture diagram

The diagram shows how the console application reaches the remote `ThirdPartyArchivalService`† through the wrapper, the generated proxy, and the HTTPS transport.

```mermaid
flowchart TD
    PROC["ThirdPartyRetentionProcessor.Execute"] --> WRAP["OnBaseService.ProcessRetention<br>hand-written wrapper"]
    WRAP --> PROXY["HylandOutBoundContractClient<br>generated proxy, one instance per run"]
    CFG["App.config client endpoint<br>binding and contract"] --> PROXY
    ENV["IEnvironmentService<br>WSPEndPointUrl setting"] --> PROXY
    PROXY --> TRANSPORT["basicHttpBinding<br>SOAP 1.1 over HTTPS"]
    TRANSPORT --> REMOTE["ThirdPartyArchivalService†<br>Hyland OnBase WSP integration*"]
```

The `*` on the `REMOTE` node label marks the "Hyland OnBase WSP integration" description as inferred from the WSDL metadata namespaces and service naming; no source document confirms it.

## Hand-written wrapper

| Field | Value |
| --- | --- |
| **Type** | `ProcessOB3PRetention.Services.OnBaseService` |
| **Source** | `ProcessOB3PRetention/Services/OnBaseService.cs` |
| **Visibility** | `public` |
| **Implements** | `IOnBaseService` (`ProcessOB3PRetention/Services/IOnBaseService.cs`). It does not implement `IDisposable` |
| **Responsibility** | Builds the `OBDocumentArchiveArchiveDocument` request from the supplied claim numbers and invokes `ArchiveDocument`. See [Business rules](business-rules.md) |
| **Proxy lifetime** | Per wrapper instance. The wrapper is held by `ThirdPartyRetentionProcessor` for the whole run |

## Endpoint resolution

| Setting | Value | Resolved from | Per-environment variance |
| --- | --- | --- | --- |
| Effective address | Value of the setting `ProcessOB3PRetention.WSPEndPointUrl` | `ProcessOB3PRetention/Services/OnBaseService.cs:19`, read through `IEnvironmentService.GetConfigSetting` from `SAIF.Framework.Core`. The value comes from the Environment API and is seeded for each track by `environmentSettings/settings.yml` (group `processob3pretention`, key `wspendpointurl`)* | `prod`: `https://onbase25prod.corp.saif.com/ThirdPartyArchivalService_Integration/SoapService.svc/SOAP11`. `entqa`: `https://onbase25qa.corp.saif.com/ThirdPartyArchivalService_Integration/SoapService.svc/SOAP11`. `npuat`: `https://onbase25npuat.corp.saif.com/ThirdPartyArchivalService_Integration/SoapService.svc/SOAP11`. All three from `environmentSettings/settings.yml`. No other track is defined, so the address on any other track cannot be resolved from this repository** |
| Configured `address` attribute (superseded at runtime) | `https://onbase25qa.corp.saif.com/ThirdPartyArchivalService_Integration/SoapService.svc/SOAP11` | `<client><endpoint address>` in `ProcessOB3PRetention/App.config`. Overridden at runtime by the constructor argument above (`ProcessOB3PRetention/Services/OnBaseService.cs:19`), so the element supplies only the binding, binding configuration, and contract*. No `App.*.config` transforms exist in the repository | None |
| Endpoint name | `BasicHttpBinding_HylandOutBoundContract` | `<client><endpoint name>` in `ProcessOB3PRetention/App.config`, selected by the literal in `ProcessOB3PRetention/Services/OnBaseService.cs:18` | None |
| Binding | `basicHttpBinding` | `<client><endpoint binding>` in `ProcessOB3PRetention/App.config` | None |
| Binding configuration | `BasicHttpBinding_HylandOutBoundContract` | `<system.serviceModel><bindings><basicHttpBinding>` in `ProcessOB3PRetention/App.config` | None |
| Contract name | `OBRetentionService.HylandOutBoundContract` | `<client><endpoint contract>` in `ProcessOB3PRetention/App.config`. Matches the generated configuration name in `Reference.cs` | None |
| Security mode | `Transport` (HTTPS) | `<security mode>` in `ProcessOB3PRetention/App.config`. The WSDL policy in `EISClientWithConfig.wsdl` also declares an HTTPS transport binding with no client certificate required | None |
| Credential mode | None. No client credential type is set, so the binding default applies. No `ClientCredentials` are assigned in code | `ProcessOB3PRetention/App.config` (no `clientCredentialType`), `ProcessOB3PRetention/Services/OnBaseService.cs`, and the generation snapshot `configuration91.svcinfo`, which records `None` | None |
| Timeouts | Not specified; transport default applies | No timeout attribute on the binding in `ProcessOB3PRetention/App.config` | None |
| Message size limits | Not specified; transport default applies | No size attribute on the binding in `ProcessOB3PRetention/App.config` | None |
| Behaviors | None declared | No `<behaviors>` element and no `behaviorConfiguration` in `ProcessOB3PRetention/App.config` | None |

The endpoint address is changeable without a rebuild through `environmentSettings/settings.yml`, because it is read from configuration at construction. The setting has no fallback: when `GetConfigSetting` returns a null or empty value, the proxy constructor fails while Autofac resolves `IOnBaseService` in `Program.CreateApplication`, outside the `try` and `catch` in `ThirdPartyRetentionProcessor.Execute`*.

The setting key is requested as `ProcessOB3PRetention.WSPEndPointUrl` in code and declared as group `processob3pretention` and key `wspendpointurl` in the deployment file. Correct resolution relies on `IEnvironmentService` matching these case-insensitively*.

### Other settings the proxy path depends on

| Setting | Source | Per-environment variance |
| --- | --- | --- |
| `processob3pretention.processbatchsize`, read by `ThirdPartyRetentionProcessor.GetProcessBatchSize` | Environment API value, seeded for each track by `environmentSettings/settings.yml`; the key itself must exist — a missing key throws `ApplicationException` rather than falling back; once a value is returned, an empty, non-numeric, zero, or negative value falls back to a code default of 100 | Seeded 200 on `prod`, `entqa`, and `npuat` |

## Lifetime and disposal

| Aspect | Finding |
| --- | --- |
| Proxy lifetime | Per consuming instance. `Program.cs` registers `OnBaseService` as `IOnBaseService` with no lifetime modifier. It is resolved once in `CreateApplication` and held by `ThirdPartyRetentionProcessor` for the whole run, so one proxy and one channel serve every batch |
| Disposal | None. `OnBaseService` is not disposable and neither `Close()` nor `Abort()` is called |
| Faulted-channel handling | None. A faulted channel is neither recovered nor released before the process exits |
| Thread safety | Not determined from source. The calls are sequential and made from one thread** |

## Integration points

| System | Type | Purpose |
| --- | --- | --- |
| `ThirdPartyArchivalService`† | SOAP service | Receives the `ArchiveDocument` call for each batch of claim numbers |
| `SAIF.Framework.Core` | Internal package | Supplies `IEnvironmentService`, which resolves the endpoint address |
| `SAIF.Framework.Windows` | Internal package | Hosts the console lifecycle that resolves and runs the wrapper* |

## Related documentation
- [Client index](index.md)
- [Overview](overview.md)
- [Contract](contract.md)
- [Operation map](operation-map.md)
- [Client reference](reference.md)
- [Consumption](consumption.md)
- [Dependencies](dependencies.md)
- [Business rules](business-rules.md)
- [Tech debt](tech-debt.md)

> **Note:** Statements marked with `†` are derived from dependency library
> documentation via the Legends CLI. Statements marked with `*` were inferred
> from code structure or contextual evidence. Statements marked with `**` could
> not be confirmed; treat as unknown until verified.

## Sources
- ProcessOB3PRetention/Connected Services/OBRetentionService/Reference.svcmap
- ProcessOB3PRetention/Connected Services/OBRetentionService/Reference.cs
- ProcessOB3PRetention/Connected Services/OBRetentionService/EISClientWithConfig.wsdl
- ProcessOB3PRetention/Connected Services/OBRetentionService/configuration91.svcinfo
- ProcessOB3PRetention/App.config
- ProcessOB3PRetention/Program.cs
- ProcessOB3PRetention/Services/OnBaseService.cs
- ProcessOB3PRetention/Services/IOnBaseService.cs
- ProcessOB3PRetention/ThirdPartyRetentionProcessor.cs
- environmentSettings/settings.yml
